#include "Character.hh"
#include "Item.hh"
#include <cstdlib>
#include <ctime>
#include <algorithm>

namespace DungeonRPG {

Character::Character(std::string name, std::string desc, unsigned hp, unsigned atk, unsigned def)
    : name(name), description(desc), health(hp), maxHealth(hp), attack(atk), defense(def) {
    // Seed random generator for stress and effects
    std::srand(static_cast<unsigned>(std::time(nullptr)));
}

Character::~Character() {
    // Cleanup inventory and accessories memory
    for (auto item : inventory) delete item;
    for (auto item : accessories) delete item;
}

bool Character::isAlive() const {
    return health > 0;
}

void Character::resetBattleBuffs() {
    // Reset all temporary combat states
    resetTemporaryDefense();
    setStunned(false);
    setMarked(false);
}

bool Character::takeDamage(unsigned damage) {
    // Apply defense (including temp) to reduce damage
    int realDefense = defense + temporaryDefense;
    int realDamage = (int)damage - realDefense;

    if (realDamage <= 0) {
        realDamage = 1; // Minimum damage of 1
    }

    if (realDamage >= (int)health) {
        health = 0;
        increaseStress(10);
        return true; // Character died
    }

    health -= realDamage;
    increaseStress(10);
    return false;
}

bool Character::performAttack(ICharacter& target) {
    // Perform simple attack on another character
    return target.takeDamage(attack);
}

std::string Character::getName() const { return name; }
std::string Character::getDescription() const { return description; }
unsigned Character::getHealth() const { return health; }
unsigned Character::getAttack() const { return attack; }
unsigned Character::getDefense() const { return defense + temporaryDefense; }

std::string Character::toString() const {
    // Display basic stats
    return name + " - HP: " + std::to_string(health) + "/" + std::to_string(maxHealth) +
           " ATK: " + std::to_string(attack) + " DEF: " + std::to_string(defense + temporaryDefense);
}

void Character::addToInventory(Item* item) {
    // Add item and apply its stat boost
    inventory.push_back(item);
    attack += item->attackBoost;
    defense += item->defenseBoost;
    maxHealth += item->healthBoost;
    health += item->healthBoost;
}

void Character::displayInventory() const {
    // Print all items in inventory
    std::cout << "Inventory:\n";
    for (size_t i = 0; i < inventory.size(); ++i) {
        std::cout << i + 1 << ". " << inventory[i]->name << " - " << inventory[i]->description << "\n";
    }
}

void Character::display() const {
    // Show character stats and equipped accessories
    std::cout << toString() << "\n";
    showAccessories();
}

void Character::increaseStress(unsigned amount) {
    // Increase stress up to max, trigger mental check if needed
    stress = std::min(stress + amount, maxStress);
    if (stress >= maxStress) checkMentalBreak();
}

void Character::heal(unsigned amount) {
    // Restore health within bounds
    health = std::min(health + amount, maxHealth);
}

void Character::relieveStress(unsigned amount) {
    // Reduce stress, clamp to zero
    if (amount >= stress) stress = 0;
    else stress -= amount;
}

void Character::checkMentalBreak() {
    // Mental state check when stress is maxed
    int roll = std::rand() % 100;
    if (roll < 25) {
        afflicted = true;
        std::cout << name << " suffers an affliction due to stress!\n";
    } else {
        virtue = true;
        std::cout << name << " rises to the challenge with virtue!\n";
    }
}

void Character::gainGold(unsigned amount) {
    gold += amount;
}

unsigned Character::getGold() const {
    return gold;
}

void Character::equipAccessory(Item* item) {
    // Equip accessory if slots are available
    if (accessories.size() >= 4) {
        std::cout << "You already have 4 accessories equipped.\n";
        return;
    }
    accessories.push_back(item);
    attack += item->attackBoost;
    defense = std::max(0, (int)defense + item->defenseBoost);
    maxHealth += item->healthBoost;
    health += item->healthBoost;
}

void Character::unequipAccessory(int index) {
    // Remove accessory by index
    if (index < 0 || index >= (int)accessories.size()) {
        std::cout << "Invalid accessory index.\n";
        return;
    }
    Item* item = accessories[index];
    attack -= item->attackBoost;
    defense -= item->defenseBoost;
    maxHealth -= item->healthBoost;
    if (health > maxHealth) health = maxHealth;
    accessories.erase(accessories.begin() + index);
    addToInventory(item);
    std::cout << "Accessory removed.\n";
}

void Character::showAccessories() const {
    // List all equipped accessories
    std::cout << "Equipped Accessories:\n";
    for (size_t i = 0; i < accessories.size(); ++i) {
        std::cout << i + 1 << ". " << accessories[i]->name << " - " << accessories[i]->description << "\n";
    }
}

void Character::applyTemporaryDefense(int amount) {
    // Add temporary defense for next battle
    temporaryDefense += amount;
}

void Character::resetTemporaryDefense() {
    temporaryDefense = 0;
}

int Character::getTemporaryDefense() const {
    return temporaryDefense;
}

void Character::setStunned(bool value) {
    stunned = value;
}

bool Character::isStunned() const {
    return stunned;
}

void Character::setMarked(bool value) {
    marked = value;
}

bool Character::isMarked() const {
    return marked;
}

}
